
import io
import json
import pathlib
import pickle
import sys
import time
import tkinter as tk
from tkinter import ttk
import cv2
import keyboard
import numpy
import pyautogui
from pymouse import PyMouse
import pyscreeze
import os
import _thread
import pynput.keyboard
import tkinter.messagebox


# 全局变量
sub_task_list = []
insert_order_list = []
out_time_list = []
out_time_dict = {}
init_param = 0


class Click:
    def __init__(self, operation_id, translate, delay_time):
        self.operation_id = operation_id
        self.translate = translate
        self.delay_time = delay_time


class Drag:
    def __init__(self, operation_id, translate_front, translate_behind, delay_time):
        self.operation_id = operation_id
        self.translate_pre = translate_front
        self.translate_behind = translate_behind
        self.delay_time = delay_time


class Input:
    def __init__(self, operation_id, text, delay_time):
        self.operation_id = operation_id
        self.text = text
        self.delay_time = delay_time


class Operation:
    def __init__(self, img_cv, main, sub, desc, threshold, operation_list):
        self.img_cv = img_cv
        self.main = main
        self.sub = sub
        self.desc = desc
        self.threshold = threshold
        self.operation_list = operation_list


def image_to_position(screen, template, threshold=0.98):  # screen：大图 template:小图，都是cv2格式 threshold：识别阈值
    image_x, image_y = template.shape[:2]
    result = cv2.matchTemplate(screen, template, cv2.TM_CCOEFF_NORMED)  # 找图函数
    min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
    if debug:
        print("识别率:", max_val, "识别阈值：", threshold)   # max_val：最大识别率
    if max_val > threshold:
        center = (max_loc[0] + image_y / 2, max_loc[1] + image_x / 2)
        return center  # 坐标
    else:
        return False


def screeze():
    pyscreeze.screenshot("screen.jpg")  # 全图截屏，保存至路径  pyscreeze.screenshot(保存路径)


def gray(img):
    # 灰度化处理
    gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    return gray_img


def find_position(screen_gray, img_path_gray, threshold=0.98):
    return image_to_position(screen_gray, img_path_gray, threshold)


def read(file):
    if file is None or file == "":
        return 0
    f = open(file, 'rb')
    r = f.read()
    f.close()
    return r


def get_img_information(img_path):
    if debug:
        print(img_path)
    r = read(img_path)
    if debug:
        print("信息长度：" + str(len(r.split(b"__information__"))))
    if len(r.split(b"__information__")) == 1:
        print("图片没有存储任何信息，无法打开")
        return 0
    img_cv = gray(cv2.imdecode(numpy.fromfile(img_path, dtype=numpy.uint8), -1))
    main = bytes.decode(r.split(b"__information__")[-2].split(b"__mainTask__")[1])
    sub = bytes.decode(r.split(b"__information__")[-2].split(b"__subTask__")[1])
    desc = bytes.decode(r.split(b"__information__")[-2].split(b"__desc__")[1])
    threshold = bytes.decode(r.split(b"__information__")[-2].split(b"__threshold__")[1])
    operation_list = pickle.load(io.BytesIO(r.split(b"__information__")[-2].split(b"__operation__")[1]))
    if debug:
        print(main, sub, desc, threshold, operation_list)
    operation = Operation(img_cv, main, sub, desc, threshold, operation_list)
    return operation
    # operation = Operation(img_cv, )


def img_database_to_list(sname):
    img_list = []
    img_path = os.path.join(os.getcwd(), "img")

    fname = main_value.get()
    img_path_second = os.path.join(img_path, fname)
    img_path_end = os.path.join(img_path_second, sname)
    for ename in os.listdir(img_path_end):
        # 打开图片 ：cv2.imdecode(numpy.fromfile(图片路径, dtype=numpy.uint8), -1)
        img_list.append(get_img_information(os.path.join(img_path_end, ename)))
        # img_list.append(gray(cv2.imdecode(numpy.fromfile(os.path.join(img_path_end, ename), dtype=numpy.uint8), -1)))
    if debug:
        print("已载入内存的图片信息：")
        print(img_list)

        # img_list.append(gray(cv2.imread(os.path.join(img_path, fname))))
    return img_list


def tasks():
    if init_param == 0:
        if init_conf() == 1:
            print("初始化成功")
        else:
            return 0
    order = 0
    sub_name = sub_task_list[order]
    new_sub_name = ""
    start_time = time.time()
    end_time = start_time
    new_order = 0
    old_images = None
    while 1:
        # try:
            if new_order >= len(sub_task_list):
                print("任务结束")
                break

            if order != new_order:
                order = new_order
                new_sub_name = sub_task_list[order]
                start_time = end_time

            if sub_name != new_sub_name:
                if new_sub_name == "":
                    new_sub_name = sub_name
                else:
                    sub_name = new_sub_name
                print("重新加载图片至内存--" + sub_name)
                images = img_database_to_list(sub_name)
                try:
                    new_order = sub_task_list.index(sub_name)
                except ValueError:
                    print("请检查配置文件执行顺序是否有问题")
                    return 0
                order = new_order
            if old_images != images and debug is True:
                print(images)
                old_images = images
                for img in images:
                    print(img.desc)
            # break
            screeze()
            screen = gray(cv2.imread('screen.jpg'))
            for img in images:
                img_cv = img.img_cv
                result = find_position(screen, img_cv, float(img.threshold))
                if type(result) is not bool:
                    print(img.main + "-" + img.sub + "-" + img.desc + "已识别,正在进行识别后的操作...")
                    print(img.operation_list)
                    for op in img.operation_list:
                        if type(op) == Click:
                            print(img.desc + "进行点击操作")
                            if op.translate == "0,0":
                                print(img.desc + "点击识别中心：", result[0], result[1])
                                PyMouse().click(int(result[0]), int(result[1]))
                            else:
                                PyMouse().click(int(op.translate.split(",")[0]), int(op.translate.split(",")[1]))
                                print(img.desc + "点击自定义坐标：" + str(int(op.translate.split(",")[0])), \
                                      str(int(op.translate.split(",")[1])))
                            print("延迟：" + op.delay_time + "毫秒")
                            time.sleep(int(op.delay_time)/1000)
                            continue
                        if type(op) == Drag:
                            print(img.desc + "进行拖拽操作")
                            if op.translate_pre == "0,0" and op.translate_behind == "0,0":
                                print(img.desc + "拖拽操作无效：" + op.translate_pre + "-->" + op.translate_behind)
                            else:
                                print(img.desc + "拖拽操作：" + op.translate_pre + "-->" + op.translate_behind)
                                displacement_x = int(op.translate_behind.split(",")[0]) - int(op.translate_pre.split(",")[0])
                                displacement_y = int(op.translate_behind.split(",")[1]) - int(op.translate_pre.split(",")[1])
                                pyautogui.moveTo(int(op.translate_pre.split(",")[0]), \
                                                 int(op.translate_pre.split(",")[1]), 0.5)
                                pyautogui.dragRel(displacement_x, displacement_y, 0.5)
                            print("延迟：" + op.delay_time + "毫秒")
                            time.sleep(int(op.delay_time) / 1000)
                            continue
                        if type(op) == Input:
                            print(img.desc + "进行输入文本操作:" + op.text)

                            if op.text == "enter" or op.text == "ENTER" or op.text == "Enter":
                                pynput.keyboard.Controller().press(pynput.keyboard.Key.enter)
                                pynput.keyboard.Controller().release(pynput.keyboard.Key.enter)
                            else:
                                for i in op.text:
                                    pynput.keyboard.Controller().press(i)
                                    pynput.keyboard.Controller().release(i)
                                    time.sleep(0.1)
                                time.sleep(int(op.delay_time) / 1000)
                                continue
                    # 判断是否跳转
                    for i in insert_order_list:
                        if i.get(img.desc) is not None:
                            print("准备跳转--" + i[img.desc])
                            if i[img.desc] == "任务退出":
                                print("任务完成！退出进程")
                                return 0
                            new_sub_name = i[img.desc]
                    end_time = time.time()
                    if end_time - start_time > int(out_time_dict[sub_name]) * 60:
                        print("超时跳转")
                        new_order = order + 1
                    else:
                        if int(end_time - start_time) / 60 % 2 == 1:
                            print(img.main + "-" + img.sub + "已运行：" + str((end_time - start_time)/60) + "分钟")
            time.sleep(0.1)
        # except Exception as e:
        #     print(e)
        #     input("Enter go")
                # _thread.start_new_thread(find_position, (screen, img))


def shut():
    while 1:
        while 1:
            keyboard.wait('F10')
            print("退出程序")
            os._exit(1)
            time.sleep(0.1)


def start():
     _thread.start_new_thread(tasks, ())
     _thread.start_new_thread(shut, ())


def init():
    global main_values
    global debug
    try:
        img_path = os.path.join(os.getcwd(), "img")
        os.mkdir(img_path)
    except FileExistsError:
        print("图片文件已创建：" + os.path.join(os.getcwd(), "img"))
    try:
        debug_path = os.path.join(img_path, "Debug.dat")
        file = open(debug_path, "r")
        if file.readline() == "True":
            debug = True
        else:
            debug = False
        file.close()
    except FileNotFoundError:
        file = open(debug_path, "w")
        debug = False
        file.close()
    # 把主任务放到数组
    img_path = os.path.join(os.getcwd(), "img")
    for fname in os.listdir(img_path):
        main_values.append(fname)


def insert():
    global insert_order_list

    def save():
        Jump = {desc_value.get(): sub_value.get()}
        insert_order_list.append(Jump)
        if debug:
            print(Jump)
            print(insert_order_list)
            print(out_time_list)

    def complete():
        global sub_task_root
        global order_root
        sub_task_root.destroy()
        insert_root.destroy()
        order_root.destroy()
        save_file = os.path.join(os.path.join(img_path, fname), "app.conf")
        print("保存至：" + save_file)
        file = open(save_file, "w+")
        write = "tasks_order:"
        for tk_str in sub_task_list:
            write = write + tk_str.get() + " "
        write = write + "\n" + "jump_dict:"
        for jump_dict in insert_order_list:
            write = write + str(jump_dict) + " "
        index = 0
        write = write + "\n" + "time_dict:"
        for time_str in out_time_list:
            time_dict = {}
            time_dict[sub_task_list[index].get()] = time_str.get()
            index = index + 1
            write = write + str(time_dict) + " "
        print(write)
        file.write(write)
        file.close()
        if debug:
            print(write)

    insert_root = tk.Toplevel()
    insert_root.geometry("+{0}+{1}".format(int(screen_width / 2.2), int(screen_height / 3)))
    insert_root.title("添加跳转字典")
    img_path = os.path.join(os.getcwd(), "img")
    fname = main_value.get()
    img_path_second = os.path.join(img_path, fname)
    desc_list = []
    desc_value = tk.StringVar()
    sub_value = tk.StringVar()
    for d in os.listdir(img_path_second):
        for desc in os.listdir(os.path.join(img_path_second, d)):
            path = os.path.join(os.path.join(img_path_second, d), desc)
            op = get_img_information(path)
            desc_list.append(op.desc)
    sub_values = os.listdir(img_path_second)
    sub_values.append("任务退出")
    desc_values_Combobox = ttk.Combobox(insert_root, state='readonly', values=desc_list, textvariable=desc_value)
    sub_values_Combobox = ttk.Combobox(insert_root, state='readonly', values=sub_values, \
                                       textvariable=sub_value)
    text = tk.Label(insert_root, text="-->")
    save_Button = tk.Button(insert_root, text="保存", command=save)
    complete_Button = tk.Button(insert_root, text="完成", command=complete)
    desc_values_Combobox.grid(row=0, column=0)
    text.grid(row=0, column=1)
    sub_values_Combobox.grid(row=0, column=2)
    save_Button.grid(row=0, column=3)
    complete_Button.grid(row=0, column=4)
    insert_root.mainloop()


def next():
    global sub_task_root
    global order_root
    sub_task_root.destroy()
    order_root = tk.Toplevel()
    order_root.geometry("+{0}+{1}".format(int(screen_width / 2.2), int(screen_height / 3)))
    order_root.title("设置子任务出口字典")
    order_text = tk.StringVar()
    order_text.set("设置子任务出口字典，点击添加按钮后，可以选择图片识别到后跳转到另一个子任务中，\n设置完成后，点击保存则可以把所有的设置保存到"
                   "本地，下次使用不需要再次设置")
    order_Label = tk.Label(order_root, textvariable=order_text)
    order_Button = tk.Button(order_root, text="添加", command=insert)
    order_Label.grid(row=0, column=0)
    order_Button.grid(row=1, column=0)


def init_conf():
    global sub_task_list
    global sub_task_root
    global out_time_list
    global init_param
    img_path = os.path.join(os.getcwd(), "img")
    fname = main_value.get()
    img_path_second = os.path.join(img_path, fname)
    save_file_path = os.path.join(img_path_second, "app.conf")
    if pathlib.Path(save_file_path).is_file():
        sub_task_list.clear()
        insert_order_list.clear()
        out_time_list.clear()
        print("正在读取配置信息：" + save_file_path)
        file = open(save_file_path, "r")
        sub_tasks_order_read = file.readline().split("tasks_order:")
        if len(sub_tasks_order_read) < 2:
            file.close()
            if tkinter.messagebox.askokcancel('提示', '配置文件已经损坏，是否删除？'):
                os.remove(save_file_path)
            return 0
        sub_task_list_read = sub_tasks_order_read[1].split(" ")
        for sub_task in sub_task_list_read:
            if sub_task == "\n":
                continue
            sub_task_list.append(sub_task)
        print("执行顺序： ", sub_task_list)
        jump_str = file.readline().split("jump_dict:")[1]
        jump_str = jump_str.replace("} {", "},{")
        for jump_dict in jump_str.split(","):
            if jump_dict == "\n":
                continue
            jump_dict = jump_dict.replace("'", '"')
            insert_order_list.append(json.loads(jump_dict))
        print("任务跳转： ", insert_order_list)
        time_str = file.readline().split("time_dict:")[1]
        time_str = time_str.replace("} {", "},{")
        for time_dict in time_str.split(","):
            time_dict = time_dict.replace("'", '"')
            time_dict = json.loads(time_dict)
            for key in time_dict:
                out_time_dict[key] = time_dict[key]
        print("超时时间： ", out_time_list)
        return 1


def get_sub_task(event):
    global sub_task_list
    global sub_task_root
    global out_time_list
    global init_param
    img_path = os.path.join(os.getcwd(), "img")
    fname = main_value.get()
    img_path_second = os.path.join(img_path, fname)
    if init_conf() == 1:
        init_param = 1
        return 0
    sub_task_root = tk.Toplevel()
    sub_task_root.geometry("+{0}+{1}".format(int(screen_width / 2.2), int(screen_height / 3)))
    sub_task_root.title("选择任务顺序和超时时间（分钟）")

    row = 0
    column = 0
    sub_task_list = []
    for sub in os.listdir(img_path_second):
        sub_value = tk.StringVar()
        time_value = tk.StringVar()
        sub_Frame = tk.Frame(sub_task_root)
        sub_Lable = tk.Label(sub_Frame, text=str(column + 1 + row * 5))
        sub_values_Combobox = ttk.Combobox(sub_Frame, state='readonly', values=os.listdir(img_path_second), textvariable=\
            sub_value)
        time_Entry = tk.Entry(sub_Frame, textvariable=time_value, width=4)
        out_time_list.append(time_value)
        sub_task_list.append(sub_value)
        sub_Lable.grid(row=0, column=0)
        sub_values_Combobox.grid(row=0, column=1)
        time_Entry.grid(row=0, column=2)
        sub_Frame.grid(row=row, column=column)
        column = column + 1
        if column == 5:
            column = 0
            row = row + 1
    order_next_button = tk.Button(sub_task_root, text="下一步", command=next)
    order_next_button.grid(row=row, column=column)


if __name__ == "__main__":
    main_values = []
    debug = False
    init()
    # ##主窗口设置##
    # 建立一个主窗口
    root = tk.Tk()
    screen_width = root.winfo_screenwidth()
    screen_height = root.winfo_screenheight()
    root.geometry("+{0}+{1}".format(int(screen_width / 2.2), int(screen_height / 3)))
    #
    main_value = tk.StringVar()
    # 窗口标题
    root.title("本地中控")
    main_Label = tk.Label(root, text="主任务名称")
    main_values_Combobox = ttk.Combobox(root, state='readonly', values=main_values, textvariable=main_value)
    main_values_Combobox.bind('<<ComboboxSelected>>', get_sub_task)
    next_button = tk.Button(root, text="ok", command=start)
    main_Label.grid(row=0, column=1)
    main_values_Combobox.grid(row=0, column=2)
    next_button.grid(row=0, column=3)
    root.mainloop()

